
package tankattack.sprites;

import gamepack.*;
import java.awt.event.KeyEvent;
import java.util.Vector;
import java.awt.*;

/** @author Somanath
*/

interface TankType { int PLAYER1=0, PLAYER2=1; }
interface TankFrame { int LEFT=0,RIGHT=1,UP=2,DOWN=3, FIRE=4, SPECIAL=5; }
interface TankState extends SpriteState { int STUN=1; }

/**  
 *   // Attributes present/assumed info here.
*/

public class Tank extends Sprite implements TankType,TankFrame,TankState {

    public static Resource r = ResourceLoader.getResource("tankattack.sprites.Tank");

	static {
	   //System.out.println("#########################  Tank.java Compiled ##########################");
	   }


	// -------------------------------------------------------------------

    public static int speed = r.getValueAsInt("speed");
	public static String bulletSpawnStr = r.getValue("bulletSpawnStr"); // expecting it to have placeholders for x,y,dir
	public static String explosionSpawnStr = r.getValue("explosionSpawnStr"); // expecting it to have placeholders for x,y
	
    public MotionController mc = new TopViewMotionController(this,speed );
    public Joypad j;
	boolean invincible;
	boolean startWithInvincibility = true;

	TimeStamp bulletSpawnTime = new TimeStamp(r.getValueAsInt("bulletSpawnTime"));
	TimeStamp invincibleTime = new TimeStamp(r.getValueAsInt("invincibleTime"));
	TimeStamp flickerTime = new TimeStamp(r.getValueAsInt("flickerTime"));
	TimeStamp stunTime = new TimeStamp(r.getValueAsInt("stunTime"));
	TimeStamp keyPressTime = new TimeStamp(r.getValueAsInt("keyPressTime"));

	//--------------------------------------------------------------------

    public boolean notify(int name,int[] value) {
		if ( name == JoypadEvent.DIRECTION_CHANGE ) 
			curFrame = dir;
		
        /*switch( name ) {
            case JoypadEvent.DIRECTION_CHANGE :  curFrame = dir;
            //case JoypadEvent.MOVEMENT: curFrame ++; if ( curFrame > len ) curFrame =0;
        }*/
        return true;
    }
	
	// <Data name="spawnformat"> x=%d:0,y=%d:0,type=%d:0:(0-player1 1-player2),dir=%d:(0:0-left 1-right 2-up 3-down) </Data>
	public Tank() { // Mandatory > x,y,type,dir
		curFrame = dir;
		res = r;
		// can make options configuration by reading sa.strArrMap 
		int[] options = null;
			setAttribute( "BLOCK" , "HURTABLE" );
			blockers = Environment.getAttributes("BLOCK");
			setZOrder( 5 );

		this.type = type;
		int[] defaultOption1 = { KeyEvent.VK_LEFT, 	KeyEvent.VK_RIGHT, 	KeyEvent.VK_UP, KeyEvent.VK_DOWN, KeyEvent.VK_CONTROL,	KeyEvent.VK_DELETE };
		int[] defaultOption2 = { KeyEvent.VK_A, 	KeyEvent.VK_D, 		KeyEvent.VK_W, 	KeyEvent.VK_S,	  KeyEvent.VK_V,		KeyEvent.VK_B,	};

        int[] vk = null;
		if( options == null ) {
			if(type == PLAYER1) vk = defaultOption1;
			if(type == PLAYER2) vk = defaultOption2;
		} else vk = options;

        j = new Joypad(Application.key,vk);
		startSprite();
		
		
	}

	public void run() {
		if ( state == Sprite.NORMAL ) { 
			normal();
		} else if (state == STUN) {
			stun();
		} else if (state == Sprite.DYING) {
			//String tmp = String.format(explosionSpawnStr,x,y);
			String spawnString = "x="+x+",y="+y+",type=0";
			Sprite.spawnClass("tankattack.sprites.Explosion",spawnString,this);	
			//Sprite.spawn( tmp, this ); 
			setState(Sprite.DEAD); 
		} else if (state == Sprite.DEAD ) {
			stopSprite();
		}
	
	/*		switch( state) {
				case DYING:		//Sprite.spawn("tankattack.sprites.Explosion","x="+x+",y="+y+",type=0"); setState(DEAD); break;
								Sprite.spawn( String.format(explosionSpawnStr,x,y), this ); setState(DEAD); break;
								//new Explosion(x,y,Explosion.BIG); setState(DEAD);	break;
				case NORMAL:	normal();	 		break;
				case STUN:		stun();     break;
				case DEAD:      stopSprite();     break;
			} */
	}

	public void normal() {

        if ( firstTime ) {
           if( startWithInvincibility ) {makeInvincible( true ); }
	        firstTime = false;
        }
		// -------- YOUR STUFF --------------
		if( invincible ) {
			if( flickerTime.elapsed() )
				visible = visible ? false : true;

			if( invincibleTime.elapsed() )
				makeInvincible( false );
		}
        mc.move( j );
		if( j.get( Joypad.ButtonA ) && bulletSpawnTime.elapsed() ) {
			fireBullet();
	    }
	}

	void stun() {
	    if ( firstTime ) {
		   flickerTime.reset();
		   stunTime.reset();
		   firstTime = false;
		}

		if( stunTime.elapsed() ) {
			visible = true;
			startWithInvincibility = false;
			setState(Sprite.NORMAL);
		}
		if( flickerTime.elapsed() )
			visible = visible ? false : true;
	}

	void makeInvincible(boolean makeIt) {
	    if ( makeIt ) {
		invincible = true;
		flickerTime.reset();
		invincibleTime.reset();
		} else {
		  invincible = false;
		  visible = true;
		}
	}

 public void handleCollision(Sprite bullet,Sprite prey) { // terminology me,mykind,mybullets,mykind's bullet, other's bullets.

        if( !bullet.valid() )  { // System.out.println("invalid bullet");      
		}
		if( !prey.valid()) {  //System.out.println("invalid prey") ;     
		}
		if( !bullet.valid() || !prey.valid()) {  //System.out.println("invalid hence returning "); 
			return;     
		}
        //System.out.println( "handleCollision(bullet=" + bullet.getShortName() + ",prey=" + prey.getShortName() + ")" );
        String preyClassName = prey.getShortName();

		String thisClassName = getShortName();  
		//System.out.println("------------- prey = " + preyClassName + " thisClassName = " + thisClassName );
        if( preyClassName.equals(thisClassName) ) {          
		  if( prey!=this ) {                     // If prey is my kind then stun it
		    //System.out.println("hit my kind but not me!!");
			prey.setState(STUN);
			bullet.setState( Sprite.DYING );
			return;
		  } else {                               // If prey is me, spare myself. s
			//System.out.println("my bullet hit me, so returning");
			return;
		  }
        }
        else if ( bullet.getShortName().equals( preyClassName ) ) {    // hmm bullet vs bullet collision
		//System.out.println("We got a Bullet Vs Bullet collision here > bullet.shortName=" + bullet.getShortName() +"---");
		if( prey.parent != null ) { //System.out.println("prey.parent.getShortName()="+prey.parent.getShortName() );
		}
		
			if ( prey.parent != null && prey.parent == this )  {    // If prey's parent me? // Oh collision with my own bullet ignore it.
				return;                                                 // spare them.
			}
		}
		// Hurt everyone else. (Have already taken care of collision with me,mybullets,mykind. 
		// Now only mykind's bullet and others need to be handled.
          bullet.setState( Sprite.DYING );
          prey.hurt( 100 ); // Strong brick won't get killed.
		  //----------------------------------------------------------
    		/*if( preyClassName.equals( "EnemyTank") ) { // Hardcoded for scoring purpose only... Rethink strategy here.
				if( prey.type == 0 || prey.type == 1 ) { // Defensive Check
					if( type == Tank.PLAYER1 ) Tank.p1Score[prey.type]++;
					if( type == Tank.PLAYER2 ) Tank.p2Score[prey.type]++;
				}
			}*/
		// If we have killed something of importance, let us inform 'any interested party'(like room) who may be tracking score.
		if ( !prey.valid() ) {  		
			String msg = (type == PLAYER1) ? "P1_KILLED_SPRITE" : "P2_KILLED_SPRITE" ;
			Notification n = new Notification(msg); // who killed P1 or P2 ?
			n.strArr = new String[] { preyClassName };			// what kind we killed
			n.intArr = new int[] { prey.type };           	// what type we killed.
			NotificationManager.sendNotification( n );					// Inform whosoever might be interested.
		}
        
	}
	public void spawnBullet(int x,int y,int dir) {
		Sprite.spawn("tankattack.sprites.Bullet # x="+x+",y="+y+",dir="+dir,this);
		
	}

	public void fireBullet() {
		Rectangle r = res.img[type][curFrame].getBounds();
		String spawnString;
		int gap = 5,speed = this.speed + 2;
		
		if ( curFrame == LEFT ) {
			Sprite.spawn( String.format(bulletSpawnStr, new Object[] { x+r.x-gap,y,WEST } ), this);
		} else if ( curFrame == RIGHT ) {
			Sprite.spawn( String.format(bulletSpawnStr, new Object[] { x+r.x+r.width+gap,y,EAST } ), this );
		} else if ( curFrame == UP ) {
			Sprite.spawn( String.format(bulletSpawnStr,new Object[] {x   ,y+r.y-gap,NORTH } ), this );
		} else if ( curFrame == DOWN ) {
			Sprite.spawn( String.format(bulletSpawnStr,new Object[] {x ,y+r.y+r.height+gap,SOUTH} ), this );
		}
		/*switch(curFrame) {
			case LEFT:	Sprite.spawn( String.format(bulletSpawnStr,x+r.x-gap,y,WEST), this );				break;			
			case RIGHT:	Sprite.spawn( String.format(bulletSpawnStr,x+r.x+r.width+gap,y,EAST), this );		break;			
			case UP:	Sprite.spawn( String.format(bulletSpawnStr,x   ,y+r.y-gap,NORTH), this );			break;
			case DOWN:	Sprite.spawn( String.format(bulletSpawnStr,x ,y+r.y+r.height+gap,SOUTH), this );	break;
		}*/
	}

	//public static void resetScores() {
	//	for(int i=0;i<2;i++)  p1Score[i] = p2Score[i] = 0;
	//}
}

